﻿using Mr.Wang.FileLog.LoggerEntity;
using Mr.Wang.FileLog.LogInterface;
using Mr.Wang.FileLog.Model;
using Mr.Wang.FileLog.PersistenceLogInfo;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Mr.Wang.FileLog
{
    public class LoggerManager : IDisposable
    {
        /// <summary>
        /// 日志队列
        /// </summary>
        readonly static ConcurrentQueue<LogInfo> logInfoQueue = new ConcurrentQueue<LogInfo>();

        /// <summary>
        /// 日志对象字典
        /// </summary>
        readonly ConcurrentDictionary<string, ILogger> loggerDic = new ConcurrentDictionary<string, ILogger>();

        /// <summary>
        /// 日志的记录者
        /// </summary>
        readonly ConcurrentBag<IPersistenceLog> persistenceLogList = new ConcurrentBag<IPersistenceLog>();

        /// <summary>
        /// 循环标识
        /// </summary>
        private bool IsLoopFlag = false;

        /// <summary>
        /// 上次检查日志记录者时间
        /// </summary>
        private DateTime lastTimeChenckLogger = DateTime.Now;

        public LoggerManager(bool isRegistFileLog = true)
        {
            if (isRegistFileLog)
            {
                RegistPersistenceLog(new FilelogPersistence());
            }
            Task.Run(WriteLogPro);
        }

        public void RegistPersistenceLog(IPersistenceLog persistenceLog)
        {
            persistenceLogList.Add(persistenceLog);
        }

        public ILogger CreateLogger(string logName)
        {
            if (!loggerDic.ContainsKey(logName))
            {
                loggerDic.TryAdd(logName, new Logger(logName));
            }
            return loggerDic[logName];
        }

        internal static void LogInfoEnQueue(LogInfo info)
        {
            logInfoQueue.Enqueue(info);
        }

        private void WriteLogPro()
        {
            IsLoopFlag = true;
            while (IsLoopFlag)
            {
                try
                {
                    if (logInfoQueue.Count > 0)
                    {
                        while (logInfoQueue.TryDequeue(out LogInfo info))
                        {
                            foreach (IPersistenceLog logger in persistenceLogList)
                            {
                                logger.MarshalLog(info);
                            }
                        }
                    }

                    if ((DateTime.Now - lastTimeChenckLogger).TotalSeconds > 10)
                    {
                        foreach (var logWriter in persistenceLogList)
                        {
                            logWriter.CheckIsWriteLog();
                        }
                        lastTimeChenckLogger = DateTime.Now;
                    }
                    Task.Delay(500);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        public void Dispose()
        {
            IsLoopFlag = false;
            Task.Delay(500);
            //程序退出所有日志立即写入
            while (logInfoQueue.TryDequeue(out LogInfo info))
            {
                foreach (IPersistenceLog logger in persistenceLogList)
                {
                    logger.PromptlyLog(info);
                }
            }
            foreach (IPersistenceLog logger in persistenceLogList)
            {
                logger.PromtlyWrite();
                logger.Dispose();
            }
        }
    }
}
